package org.xmap.net;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

import org.xmap.ui.ViewManager;

/**
 * Http连接器，该类只有一个发送Http请求的静态方法。
 *
 * @author Zealot
 *
 */
public class HttpConnector {

    private static Hashtable commonProperty = new Hashtable(); // 存储通用的属性

    public static void putCommonProperty(String key, String value) {
        HttpConnector.commonProperty.put(key, value);
    }

    public static void removeCommonProperty(String key) {
        HttpConnector.commonProperty.remove(key);
    }

    public static byte[] sendHttpRequestSync(HttpRequest httpRequest, boolean isProxy, HttpListener httpListener) {
        if (httpRequest == null) {
            return null;
        }

        URL destUrl = httpRequest.getUrl();
        if (destUrl == null || destUrl.getUrl() == null || destUrl.getUrl().length() == 0) {
            return null;
        }

        String method = httpRequest.getMethod();
        Hashtable headers = httpRequest.getHeaders();
        byte[] postData = httpRequest.getPostData();
        HttpConnection conn = null;
        InputStream is = null;
        try {
            String request;
            if (isProxy) { // x-online-host
                request = "http://10.0.0.172:80" + destUrl.getPath();
            } else { // no proxy
                request = destUrl.getUrl();
            }
            if (httpListener != null) {
                httpListener.onConnect();
            }

            if (HttpConnection.POST.equals(method)) {
                ViewManager.instance.debugPrint("POST:" + request);
                conn = (HttpConnection) Connector.open(request, Connector.READ_WRITE, true);
//                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                conn.setRequestProperty("Content-Length", Integer.toString(postData == null ? 0 : (postData.length)));
            } else {
                ViewManager.instance.debugPrint("GET:" + request);
                conn = (HttpConnection) Connector.open(request, Connector.READ, true);
            }

            if (isProxy) {
                conn.setRequestProperty("X-Online-Host", destUrl.getHost() + ":" + destUrl.getPort());
                ViewManager.instance.debugPrint("par:" + destUrl.getHost() + ":" + destUrl.getPort());
            }

            if (HttpConnector.commonProperty.size() > 0) {
//                ViewManager.instance.debugPrint("size:" + HttpConnector.commonProperty.size());
                Enumeration e = HttpConnector.commonProperty.keys();
                while (e.hasMoreElements()) {
                    String key = (String) e.nextElement();
                    String value = (String) HttpConnector.commonProperty.get(key);
                    if (key != null && value != null) {
                        conn.setRequestProperty(key, value);
                    }
//                    ViewManager.instance.debugPrint("key:" + key + " value:" + value);
                }
            }
//            ViewManager.instance.debugPrint("init par finish!");
            conn.setRequestProperty("Accept", "*/*");
            conn.setRequestMethod(method);
            if (headers != null) {
                Enumeration e = headers.keys();
                while (e.hasMoreElements()) {
                    String key = (String) e.nextElement();
                    String value = (String) headers.get(key);
                    conn.setRequestProperty(key, value);
                }
            }

            if (HttpConnection.POST.equals(method) && postData != null) {
                OutputStream outputstream = conn.openOutputStream();
                outputstream.write(postData);
                // #if (QD || N7610 || N3650 || SE)
                // # //outputstream.flush();
                // #endif
                outputstream.close();
            }
            ViewManager.instance.debugPrint("准备发送请求!");
            int responseCode = conn.getResponseCode();
            ViewManager.instance.debugPrint("resCode:" + responseCode);
            if (httpListener != null) {
                httpListener.onConnected(conn, responseCode);
            }

            int headerIndex = 0;
            boolean isSkip = false;
            while (true) {
                String headerKey = conn.getHeaderFieldKey(headerIndex);
                String headerField = conn.getHeaderField(headerIndex);
                if (headerKey == null) {
                    break;
                }
                ViewManager.instance.debugPrint("==" + headerKey + ":" + headerField);
                // 下面这部分代码是因为早期在测试的时候，发现有时候连接网络的时候，部分卡联网会有跳转页面，所以发现这种情况，再发送一次请求
                if (headerKey.toLowerCase().equals("server")) {
                    if (headerField.toLowerCase().indexOf("weblogic server") != -1) {
                        ViewManager.instance.debugPrint("发现移动跳转属性");
//                        isSkip = true; // 移动返回的跳转页面的头属性里头带有server参数，并且server的参数的值为weblogic
                    }
                }
                headerIndex++;
            }

            if (responseCode != HttpConnection.HTTP_OK) {
                return null;
            }
            if (isSkip) {
                ViewManager.instance.debugPrint("发现跳转页面=============");
                is = conn.openInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 把跳转页面打印出来
                int bytesread = 0;
                byte[] tmpdata = new byte[256];
                while ((bytesread = is.read(tmpdata)) != -1) {
                    baos.write(tmpdata, 0, bytesread);
                }
                byte[] tmp = baos.toByteArray();
                ViewManager.instance.debugPrint(new String(tmp, "UTF-8"));

                try {
                    is.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                is = null;

                try {
                    conn.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    if (httpListener != null) {
                        httpListener.onError(e.getMessage());
                    }
                }
                conn = null;

                byte[] data = HttpConnector.sendHttpRequestSync(httpRequest, isProxy, httpListener); // 重新请求，直到获得数据
                return data;
            } else {
                is = conn.openInputStream();
                int len = (int) conn.getLength();
                ViewManager.instance.debugPrint("length from header:" + len);
                if (httpListener != null && httpListener.isStreamMode()) { // 有监听器，把数据通过接口传出去。

                    // todo 测试

//                    byte[] data = null;
//                    if (len > 0) {
//                        int actual = 0;
//                        int bytesread = 0;
//                        data = new byte[len];
//                        while ((bytesread != len) && (actual != -1)) {
//                            actual = is.read(data, bytesread, len - bytesread);
//                            bytesread += actual;
//                        }
//                    } else {
//                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
//                        int bytesread = 0;
//                        byte[] tmpdata = new byte[256];
//                        while ((bytesread = is.read(tmpdata)) != -1) {
//                            baos.write(tmpdata, 0, bytesread);
//                        }
//                        data = baos.toByteArray();
//                    }
//                    ViewManager.instance.debugPrint(new String(data, "UTF-8"));
//                    ByteArrayInputStream bais = new ByteArrayInputStream(data);
//                    httpListener.onRecvingData(data.length, bais);


                    httpListener.onRecvingData(len, is);
                } else {
                    byte[] data = null;
                    if (len > 0) {
                        int actual = 0;
                        int bytesread = 0;
                        data = new byte[len];
                        while ((bytesread != len) && (actual != -1)) {
                            actual = is.read(data, bytesread, len - bytesread);
                            bytesread += actual;
                        }
                    } else {
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        int bytesread = 0;
                        byte[] tmpdata = new byte[256];
                        while ((bytesread = is.read(tmpdata)) != -1) {
                            baos.write(tmpdata, 0, bytesread);
                        }
                        data = baos.toByteArray();
                    }
                    ViewManager.instance.debugPrint("length read:" + data.length);
                    if (httpListener != null) {
                        httpListener.onRecvedData(data);
                    } else {
                        return data;
                    }
                }
            }
        } catch (SecurityException e) {
            ViewManager.instance.debugPrint("SecurityException为：" + e.getMessage());
            String msg = e.getMessage() + "SecurityException";
            if (httpListener != null) {
                httpListener.onError(msg);
            }
        } catch (ConnectionNotFoundException e) {
            ViewManager.instance.debugPrint("ConnectionNotFoundException为：" + e.getMessage());
            String msg = e.getMessage() + "ConnectionNotFoundException";
            if (httpListener != null) {
                httpListener.onError(msg);
            }
        } catch (IllegalArgumentException e) {
            ViewManager.instance.debugPrint("IllegalArgumentException为：" + e.getMessage());
            String msg = e.getMessage() + "ConnectionNotFoundException";
            if (httpListener != null) {
                httpListener.onError(msg);
            }
        } catch (Exception e) {
            String msg = e.getMessage();
            ViewManager.instance.debugPrint("Exception为：" + msg);
            if (msg != null && msg.indexOf("-36") != -1) { // 在nokia n73机器上有时候会出现-36错误，重新连接
                ViewManager.instance.debugPrint("-36 error, reconnect!");
                return HttpConnector.sendHttpRequestSync(httpRequest, isProxy, httpListener);
            } else {
                ViewManager.instance.debugPrint("error:" + e.getMessage());
                if (httpListener != null) {
                    httpListener.onError(e.getMessage());
                }
            }
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    if (httpListener != null) {
                        httpListener.onError(e.getMessage());
                    }
                }
                is = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (Exception e) {
                    e.printStackTrace();
                    if (httpListener != null) {
                        httpListener.onError(e.getMessage());
                    }
                }
                conn = null;
            }
        }
        return null;
    }
}
